/*************************************************************************** * Copyright (C) 2003-2007 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. ***************************************************************************/ package org.exoplatform.platform.gadget.services.LoginHistory; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.query.Query; import javax.jcr.query.QueryManager; import javax.jcr.query.QueryResult; import org.exoplatform.container.ExoContainerContext; import org.exoplatform.container.xml.InitParams; import org.exoplatform.container.xml.ValueParam; import org.exoplatform.services.jcr.RepositoryService; import org.exoplatform.services.jcr.access.PermissionType; import org.exoplatform.services.jcr.core.ExtendedNode; import org.exoplatform.services.jcr.core.ManageableRepository; import org.exoplatform.services.jcr.ext.common.SessionProvider; import org.exoplatform.services.jcr.impl.core.query.QueryImpl; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.organization.OrganizationService; import org.picocontainer.Startable; /** * Created by The eXo Platform SARL Author : Tung Vu Minh tungvm@exoplatform.com * Apr 21, 2011 6:19:21 PM */ public class LoginHistoryServiceImpl implements LoginHistoryService, Startable { private static final Log LOG = ExoLogger.getLogger(LoginHistoryServiceImpl.class); private static String HOME = "exo:LoginHistoryHome"; private static String LOGIN_HISTORY = "loginHistory"; private static String LOGIN_COUNTER = "loginCounter"; private static String BEFORE_LAST_LOGIN = "exo:LoginHisSvc_beforeLastLogin"; private static String LAST_LOGIN_TIME = "exo:LoginHisSvc_lastLogin"; private static int MAX_NUM_OF_LOGIN_HISTORY_ENTRIES = 0; private static int DAYS_FOR_KEEPING_USER_STATISTIC = 0; private static int DAYS_FOR_KEEPING_GLOBAL_STATISTIC = 0; private static long DAY_IN_MILLISEC = 86400000; private RepositoryService repositoryService; /** * Init LoginHistoryServiceImpl with RepositoryService from the container. * * @param repositoryService */ public LoginHistoryServiceImpl(RepositoryService repositoryService) { this.repositoryService = repositoryService; } @Override public void start() { // Create login history node try { createHomeNode(); } catch (RepositoryException e) { LOG.error("Error of LoginHistoryServiceImpl start: " + e.getMessage(), e); throw new RuntimeException(e); } } @Override public void stop() { // do nothing } /** * Create exo:LoginHistoryHome node. * * @throws RepositoryException */ protected void createHomeNode() throws RepositoryException { SessionProvider sProvider = SessionProvider.createSystemProvider(); try { ManageableRepository currentRepo = this.repositoryService.getCurrentRepository(); Session session = sProvider.getSession(currentRepo.getConfiguration().getDefaultWorkspaceName(), currentRepo); Node rootNode = session.getRootNode(); if (!rootNode.hasNode(HOME)) { Node homeNode = rootNode.addNode(HOME, "exo:LoginHisSvc_loginHistoryService"); homeNode.addMixin("exo:privilegeable"); Map<String, String[]> permissions = new HashMap<String, String[]>(); permissions.put("*:/platform/administrators", PermissionType.ALL); permissions.put("*:/platform/users", new String[]{PermissionType.READ}); ((ExtendedNode)homeNode).setPermissions(permissions); homeNode.addMixin("exo:owneable"); rootNode.save(); // --- PLF-2493 : Umbrella for usability issues if (homeNode.canAddMixin("exo:hiddenable")) { homeNode.addMixin("exo:hiddenable"); } Node globalLoginCounterNode = homeNode.addNode(ALL_USERS, "exo:LoginHisSvc_globalLoginCounter"); globalLoginCounterNode.setProperty("exo:LoginHisSvc_globalLoginCounter_lastIndex", 0); homeNode.save(); LOG.info("Login history storage initialized."); } } finally { sProvider.close(); } } /** * Apply configurations from service's xml */ public void addConfiguration(LoginHistoryPlugin plugin) { InitParams initParams = plugin.getInitParams(); if (initParams != null) { ValueParam MaxNumOfUserLoginHistoryEntries = initParams.getValueParam("MaxNumOfUserLoginHistoryEntries"); if (MaxNumOfUserLoginHistoryEntries != null) MAX_NUM_OF_LOGIN_HISTORY_ENTRIES = Integer.parseInt(MaxNumOfUserLoginHistoryEntries.getValue()); ValueParam DaysForKeepingUserStatistic = initParams.getValueParam("DaysForKeepingUserStatistic"); if (DaysForKeepingUserStatistic != null) DAYS_FOR_KEEPING_USER_STATISTIC = Integer.parseInt(DaysForKeepingUserStatistic.getValue()); ValueParam DaysForKeepingGlobalStatistic = initParams.getValueParam("DaysForKeepingGlobalStatistic"); if (DaysForKeepingGlobalStatistic != null) DAYS_FOR_KEEPING_GLOBAL_STATISTIC = Integer.parseInt(DaysForKeepingGlobalStatistic.getValue()); } } /** * Get user's last login time */ public long getLastLogin(String userId) throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); try { Session session = this.getSession(sProvider); Node homeNode = session.getRootNode().getNode(HOME); return !homeNode.hasNode(userId) ? 0 : homeNode.getNode(userId).getProperty("exo:LoginHisSvc_lastLogin").getLong(); } catch (Exception e) { LOG.debug("Error while retrieving " + userId + "'s last login: " + e.getMessage(), e); throw e; } finally { sProvider.close(); } } /** * Get last logins * * @param numItems * @return List of {numItems} last login entries * @throws Exception */ public List<LastLoginBean> getLastLogins(int numItems, String userIdFilter) throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); try { Session session = this.getSession(sProvider); QueryManager queryManager = session.getWorkspace().getQueryManager(); String sqlStatement = "SELECT * FROM exo:LoginHisSvc_userProfile " + "WHERE (UPPER(exo:LoginHisSvc_userId) LIKE '%" + userIdFilter.toUpperCase() + "%') OR (UPPER(exo:LoginHisSvc_userName) LIKE '%" + userIdFilter.toUpperCase() + "%') " + "ORDER BY exo:LoginHisSvc_lastLogin DESC"; QueryImpl query = (QueryImpl) queryManager.createQuery(sqlStatement, Query.SQL); query.setLimit(numItems); QueryResult result = query.execute(); NodeIterator nodeIterator = result.getNodes(); List<LastLoginBean> lastLogins = new ArrayList<LastLoginBean>(); Node node; String userId, userName; while (nodeIterator.hasNext()) { node = nodeIterator.nextNode(); LastLoginBean lastLoginBean = new LastLoginBean(); userId = node.getName(); userName = node.getProperty("exo:LoginHisSvc_userName").getString(); lastLoginBean.setUserId(userId); lastLoginBean.setUserName(userName.isEmpty() ? userId : userName); lastLoginBean.setLastLogin(node.getProperty("exo:LoginHisSvc_lastLogin").getLong()); lastLoginBean.setBeforeLastLogin(node.getProperty("exo:LoginHisSvc_beforeLastLogin").getLong()); lastLogins.add(lastLoginBean); } return lastLogins; } catch (Exception e) { LOG.debug("Error while retrieving last logins: " + e.getMessage(), e); throw e; } finally { sProvider.close(); } } /** * Add an entry to user login history * * @param userId * @param loginTime * @throws Exception */ public void addLoginHistoryEntry(String userId, long loginTime) throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); try { Session session = this.getSession(sProvider); Node homeNode = session.getRootNode().getNode(HOME); Node userNode, loginHistoryNode, loginCounterNode, globalLoginCounterNode; String userName = getUserFullName(userId); if (!homeNode.hasNode(userId)) { userNode = homeNode.addNode(userId, "exo:LoginHisSvc_userProfile"); userNode.setProperty("exo:LoginHisSvc_userId", userId); userNode.setProperty("exo:LoginHisSvc_userName", userName); userNode.setProperty("exo:LoginHisSvc_lastLogin", 0); userNode.setProperty("exo:LoginHisSvc_beforeLastLogin", 0); homeNode.save(); loginHistoryNode = userNode.addNode(LOGIN_HISTORY, "exo:LoginHisSvc_loginHistory"); loginHistoryNode.setProperty("exo:LoginHisSvc_loginHistory_lastIndex", 0); loginCounterNode = userNode.addNode(LOGIN_COUNTER, "exo:LoginHisSvc_loginCounter"); loginCounterNode.setProperty("exo:LoginHisSvc_loginCounter_lastIndex", 0); userNode.save(); } else { userNode = homeNode.getNode(userId); } userNode.setProperty("exo:LoginHisSvc_userName", userName); userNode.setProperty("exo:LoginHisSvc_beforeLastLogin", userNode.getProperty("exo:LoginHisSvc_lastLogin").getLong()); userNode.setProperty("exo:LoginHisSvc_lastLogin", loginTime); // Update login history loginHistoryNode = userNode.getNode("loginHistory"); long loginHistory_lastIndex = loginHistoryNode.getProperty("exo:LoginHisSvc_loginHistory_lastIndex").getLong(); loginHistory_lastIndex++; Node loginHistory_loginTimeNode = loginHistoryNode.addNode(Long.toString(loginHistory_lastIndex), "exo:LoginHisSvc_loginHistoryItem"); loginHistory_loginTimeNode.setProperty("exo:LoginHisSvc_loginHistoryItem_id", loginHistory_lastIndex); loginHistory_loginTimeNode.setProperty("exo:LoginHisSvc_loginHistoryItem_userId", userId); loginHistory_loginTimeNode.setProperty("exo:LoginHisSvc_loginHistoryItem_loginTime", loginTime); // Keep only up to MAX_NUM_OF_LOGIN_HISTORY_ENTRIES last items if (MAX_NUM_OF_LOGIN_HISTORY_ENTRIES > 0 && loginHistory_lastIndex > MAX_NUM_OF_LOGIN_HISTORY_ENTRIES) { QueryManager queryManager = session.getWorkspace().getQueryManager(); String sqlStatement = "SELECT * FROM exo:LoginHisSvc_loginHistoryItem " + "WHERE exo:LoginHisSvc_loginHistoryItem_userId = '" + userId + "' " + "AND exo:LoginHisSvc_loginHistoryItem_id <= " + Long.toString(loginHistory_lastIndex - MAX_NUM_OF_LOGIN_HISTORY_ENTRIES); QueryImpl query = (QueryImpl) queryManager.createQuery(sqlStatement, Query.SQL); QueryResult result = query.execute(); NodeIterator nodeIterator = result.getNodes(); while (nodeIterator.hasNext()) { Node node = nodeIterator.nextNode(); node.remove(); } } loginHistoryNode.setProperty("exo:LoginHisSvc_loginHistory_lastIndex", loginHistory_lastIndex); Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(loginTime); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); String loginDate = Long.toString(cal.getTimeInMillis()); // Update login counter loginCounterNode = userNode.getNode("loginCounter"); long loginCounter_lastIndex = loginCounterNode.getProperty("exo:LoginHisSvc_loginCounter_lastIndex").getLong(); Node loginCounter_loginDateNode; if (!loginCounterNode.hasNode(loginDate)) { loginCounter_loginDateNode = loginCounterNode.addNode(loginDate, "exo:LoginHisSvc_loginCounterItem"); loginCounter_lastIndex++; loginCounter_loginDateNode.setProperty("exo:LoginHisSvc_loginCounterItem_id", loginCounter_lastIndex); loginCounter_loginDateNode.setProperty("exo:LoginHisSvc_loginCounterItem_userId", userId); loginCounter_loginDateNode.setProperty("exo:LoginHisSvc_loginCounterItem_loginDate", Long.parseLong(loginDate)); loginCounter_loginDateNode.setProperty("exo:LoginHisSvc_loginCounterItem_loginCount", 1); } else { loginCounter_loginDateNode = loginCounterNode.getNode(loginDate); long loginCount = loginCounter_loginDateNode.getProperty("exo:LoginHisSvc_loginCounterItem_loginCount").getLong(); loginCounter_loginDateNode.setProperty("exo:LoginHisSvc_loginCounterItem_loginCount", loginCount + 1); } // Keep only up to DAYS_FOR_KEEPING_USER_STATISTIC last items if (DAYS_FOR_KEEPING_USER_STATISTIC > 0 && loginCounter_lastIndex > DAYS_FOR_KEEPING_USER_STATISTIC) { QueryManager queryManager = session.getWorkspace().getQueryManager(); String sqlStatement = "SELECT * FROM exo:LoginHisSvc_loginCounterItem " + "WHERE exo:LoginHisSvc_loginCounterItem_userId = '" + userId + "' " + "AND exo:LoginHisSvc_loginCounterItem_id <= " + Long.toString(loginCounter_lastIndex - DAYS_FOR_KEEPING_USER_STATISTIC); QueryImpl query = (QueryImpl) queryManager.createQuery(sqlStatement, Query.SQL); QueryResult result = query.execute(); NodeIterator nodeIterator = result.getNodes(); Node node; while (nodeIterator.hasNext()) { node = nodeIterator.nextNode(); node.remove(); } } loginCounterNode.setProperty("exo:LoginHisSvc_loginCounter_lastIndex", loginCounter_lastIndex); // Update global login counter globalLoginCounterNode = session.getRootNode().getNode(HOME).getNode(ALL_USERS); long globalLoginCounter_lastIndex = globalLoginCounterNode.getProperty("exo:LoginHisSvc_globalLoginCounter_lastIndex").getLong(); Node globalLoginCounter_loginDateNode; if (!globalLoginCounterNode.hasNode(loginDate)) { globalLoginCounter_loginDateNode = globalLoginCounterNode.addNode(loginDate, "exo:LoginHisSvc_loginCounterItem"); globalLoginCounter_lastIndex++; globalLoginCounter_loginDateNode.setProperty("exo:LoginHisSvc_loginCounterItem_id", globalLoginCounter_lastIndex); globalLoginCounter_loginDateNode.setProperty("exo:LoginHisSvc_loginCounterItem_userId", ALL_USERS); globalLoginCounter_loginDateNode.setProperty("exo:LoginHisSvc_loginCounterItem_loginDate", Long.parseLong(loginDate)); globalLoginCounter_loginDateNode.setProperty("exo:LoginHisSvc_loginCounterItem_loginCount", 1); } else { globalLoginCounter_loginDateNode = globalLoginCounterNode.getNode(loginDate); long loginCount = globalLoginCounter_loginDateNode.getProperty("exo:LoginHisSvc_loginCounterItem_loginCount").getLong(); globalLoginCounter_loginDateNode.setProperty("exo:LoginHisSvc_loginCounterItem_loginCount", loginCount + 1); } // Keep only up to DAYS_FOR_KEEPING_GLOBAL_STATISTIC last items if (DAYS_FOR_KEEPING_GLOBAL_STATISTIC > 0 && globalLoginCounter_lastIndex > DAYS_FOR_KEEPING_GLOBAL_STATISTIC) { QueryManager queryManager = session.getWorkspace().getQueryManager(); String sqlStatement = "SELECT * FROM exo:LoginHisSvc_loginCounterItem " + "WHERE exo:LoginHisSvc_loginCounterItem_userId = '" + ALL_USERS + "' " + "AND exo:LoginHisSvc_loginCounterItem_id <= " + Long.toString(globalLoginCounter_lastIndex - DAYS_FOR_KEEPING_GLOBAL_STATISTIC); QueryImpl query = (QueryImpl) queryManager.createQuery(sqlStatement, Query.SQL); QueryResult result = query.execute(); NodeIterator nodeIterator = result.getNodes(); Node node; while (nodeIterator.hasNext()) { node = nodeIterator.nextNode(); node.remove(); } } globalLoginCounterNode.setProperty("exo:LoginHisSvc_globalLoginCounter_lastIndex", globalLoginCounter_lastIndex); userNode.save(); globalLoginCounterNode.save(); } catch (Exception e) { LOG.debug("Error while adding login history entry for user '" + userId + "': " + e.getMessage(), e); throw e; } finally { sProvider.close(); } } /** * Get user login history * * @param userId * @return List of login history entries in range [fromTime..toTime] of user {userId} * @throws Exception */ public List<LoginHistoryBean> getLoginHistory(String userId, long fromTime, long toTime) throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); try { Session session = this.getSession(sProvider); QueryManager queryManager = session.getWorkspace().getQueryManager(); String sqlStatement = "SELECT * FROM exo:LoginHisSvc_loginHistoryItem " + "WHERE " + (userId.equals(LoginHistoryService.ALL_USERS) ? "" : "exo:LoginHisSvc_loginHistoryItem_userId = '" + userId + "' AND ") + "(exo:LoginHisSvc_loginHistoryItem_loginTime BETWEEN " + Long.toString(fromTime) + " AND " + Long.toString(toTime) + ") " + "ORDER BY exo:LoginHisSvc_loginHistoryItem_loginTime DESC"; QueryImpl query = (QueryImpl) queryManager.createQuery(sqlStatement, Query.SQL); QueryResult result = query.execute(); NodeIterator nodeIterator = result.getNodes(); List<LoginHistoryBean> list = new ArrayList<LoginHistoryBean>(); Node node; String uId, uName; while (nodeIterator.hasNext()) { node = nodeIterator.nextNode(); LoginHistoryBean loginHistory = new LoginHistoryBean(); uId = node.getProperty("exo:LoginHisSvc_loginHistoryItem_userId").getString(); uName = getUserFullName(uId); loginHistory.setUserId(uId); loginHistory.setUserName(uName.isEmpty() ? uId : uName); loginHistory.setLoginTime(node.getProperty("exo:LoginHisSvc_loginHistoryItem_loginTime").getLong()); list.add(loginHistory); } return list; } catch (Exception e) { LOG.debug("Error while getting login history of user '" + userId + "': " + e.getMessage(), e); throw e; } finally { sProvider.close(); } } /** * Get user's login count per days in range [fromDate..toDate] */ public List<LoginCounterBean> getLoginCountPerDaysInRange(String userId, long fromDate, long toDate) throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); try { Session session = this.getSession(sProvider); QueryManager queryManager = session.getWorkspace().getQueryManager(); String sqlStatement = "SELECT * FROM exo:LoginHisSvc_loginCounterItem " + "WHERE exo:LoginHisSvc_loginCounterItem_userId = '" + userId + "' " + "AND (exo:LoginHisSvc_loginCounterItem_loginDate BETWEEN " + Long.toString(fromDate) + " AND " + Long.toString(toDate) + ") " + "ORDER BY exo:LoginHisSvc_loginCounterItem_loginDate ASC"; QueryImpl query = (QueryImpl) queryManager.createQuery(sqlStatement, Query.SQL); QueryResult result = query.execute(); NodeIterator nodeIterator = result.getNodes(); List<LoginCounterBean> list = new ArrayList<LoginCounterBean>(); Node node; while (nodeIterator.hasNext()) { node = nodeIterator.nextNode(); LoginCounterBean loginCountPerDay = new LoginCounterBean(); loginCountPerDay.setLoginDate(node.getProperty("exo:LoginHisSvc_loginCounterItem_loginDate").getLong()); loginCountPerDay.setLoginCount(node.getProperty("exo:LoginHisSvc_loginCounterItem_loginCount").getLong()); list.add(loginCountPerDay); } return list; } catch (Exception e) { LOG.debug("Error while getting login counts of user '" + userId + "': " + e.getMessage(), e); throw e; } finally { sProvider.close(); } } /** * Get user login count * * @return: The total number of logins since {fromDate} to {toDate} of user {userId} */ private int getLoginCount(String userId, long fromDate, long toDate) throws Exception { List<LoginCounterBean> loginCounts = getLoginCountPerDaysInRange(userId, fromDate, toDate); int sum = 0; Iterator<LoginCounterBean> iter = loginCounts.iterator(); while (iter.hasNext()) { sum += iter.next().getLoginCount(); } return sum; } /** * Get user login count per days in given week */ public List<LoginCounterBean> getLoginCountPerDaysInWeek(String userId, long week) throws Exception { List<LoginCounterBean> list = new ArrayList<LoginCounterBean>(); List<Long> days = new ArrayList<Long>(); long now = System.currentTimeMillis(); long nextWeek = nextMonday(week); long day = week; LoginCounterBean loginCountPerDay; do { loginCountPerDay = new LoginCounterBean(); loginCountPerDay.setLoginDate(day); loginCountPerDay.setLoginCount(day > now ? -1 : 0); list.add(loginCountPerDay); days.add(day); day += DAY_IN_MILLISEC; } while (day < nextWeek); List<LoginCounterBean> counters = getLoginCountPerDaysInRange(userId, week, nextMonday(week) - DAY_IN_MILLISEC); Iterator<LoginCounterBean> iter = counters.iterator(); while (iter.hasNext()) { loginCountPerDay = iter.next(); list.set(days.indexOf(loginCountPerDay.getLoginDate()), loginCountPerDay); } return list; } /** * Get user login count per weeks in given month */ public List<LoginCounterBean> getLoginCountPerWeeksInMonths(String userId, long fromMonth, int numOfMonths) throws Exception { Calendar cal = Calendar.getInstance(); long now = cal.getTime().getTime(); cal.setTimeInMillis(fromMonth); cal.add(Calendar.MONTH, numOfMonths); long toMonth = cal.getTimeInMillis(); long fromDate, toDate = fromMonth; List<LoginCounterBean> list = new ArrayList<LoginCounterBean>(); do { fromDate = toDate; toDate = nextMonday(toDate); if (toDate > toMonth) toDate = toMonth; LoginCounterBean loginCountPerWeek = new LoginCounterBean(); loginCountPerWeek.setLoginDate(fromDate); loginCountPerWeek.setLoginCount(fromDate > now ? -1 : getLoginCount(userId, fromDate, toDate - DAY_IN_MILLISEC)); list.add(loginCountPerWeek); } while (toDate < toMonth); return list; } /** * Get user login count per months in given year */ public List<LoginCounterBean> getLoginCountPerMonthsInYear(String userId, long year) throws Exception { Calendar cal = Calendar.getInstance(); long now = cal.getTime().getTime(); cal.setTimeInMillis(year); cal.add(Calendar.YEAR, 1); long nextYear = cal.getTimeInMillis(); long fromDate, toDate = year; List<LoginCounterBean> list = new ArrayList<LoginCounterBean>(); do { fromDate = toDate; cal.setTimeInMillis(toDate); cal.add(Calendar.MONTH, 1); toDate = cal.getTimeInMillis(); if (toDate > nextYear) toDate = nextYear; LoginCounterBean loginCountPerWeek = new LoginCounterBean(); loginCountPerWeek.setLoginDate(fromDate); loginCountPerWeek.setLoginCount(fromDate > now ? -1 : getLoginCount(userId, fromDate, toDate - DAY_IN_MILLISEC)); list.add(loginCountPerWeek); } while (toDate < nextYear); return list; } /** * Utility function to get JCR session in current repository * * @param sessionProvider * @return JCR session * @throws Exception */ private Session getSession(SessionProvider sessionProvider) throws Exception { ManageableRepository currentRepo = this.repositoryService.getCurrentRepository(); return sessionProvider.getSession(currentRepo.getConfiguration().getDefaultWorkspaceName(), currentRepo); } private static long nextMonday(long date) { Calendar now = Calendar.getInstance(); now.setTimeInMillis(date); int weekday = now.get(Calendar.DAY_OF_WEEK); // calculate how much to add // the 2 is the difference between Saturday and Monday int days = weekday == Calendar.SUNDAY ? 1 : Calendar.SATURDAY - weekday + 2; now.add(Calendar.DAY_OF_YEAR, days); return now.getTimeInMillis(); } private String getUserFullName(String userId) { try { OrganizationService service = (OrganizationService) ExoContainerContext.getCurrentContainer() .getComponentInstanceOfType(OrganizationService.class); return service.getUserHandler().findUserByName(userId).getFullName(); } catch (Exception e) { return userId; } } /** * Get the list of all users who are logged after fromTime * * @param fromTime * @return the list of user's name */ public Set<String> getLastUsersLogin(long fromTime) throws Exception { Set<String> users = new LinkedHashSet<String>(); SessionProvider sProvider = SessionProvider.createSystemProvider(); try { Session session = this.getSession(sProvider); QueryManager queryManager = session.getWorkspace().getQueryManager(); StringBuilder sb = new StringBuilder(); sb.append("SELECT * FROM exo:LoginHisSvc_userProfile WHERE") .append(" exo:LoginHisSvc_lastLogin >= " + Long.toString(fromTime)) .append(" ORDER BY exo:LoginHisSvc_lastLogin DESC"); QueryImpl query = (QueryImpl) queryManager.createQuery(sb.toString(), Query.SQL); QueryResult result = query.execute(); NodeIterator nodeIterator = result.getNodes(); while (nodeIterator.hasNext()) { Node node = nodeIterator.nextNode(); String userId = node.getProperty("exo:LoginHisSvc_userId").getString(); users.add(userId); } return users; } catch (Exception e) { LOG.debug("Error while getting login history of users " + e.getMessage(), e); } finally { sProvider.close(); } return null; } /** * An user is inactive if his last login is more than a number of days * * @param userId user's name * @param days the number of days to verify if user is active or not * @return */ public boolean isActiveUser(String userId, int days) { SessionProvider sProvider = SessionProvider.createSystemProvider(); try { Session session = this.getSession(sProvider); Node homeNode = session.getRootNode().getNode(HOME); if (! homeNode.hasNode(userId)) { return false; } Node userNode = homeNode.getNode(userId); long beforeLastLogin = userNode.getProperty(BEFORE_LAST_LOGIN).getLong(); // return true if it's the first login of user if (beforeLastLogin == 0) return true; // Calendar cal = Calendar.getInstance(); cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH) - days); long limitTime = cal.getTimeInMillis(); return beforeLastLogin >= limitTime; } catch (Exception e) { LOG.error("Error while get the last login of current user", e); } return false; } public Map<String, Integer> getActiveUsers(long fromTime) { Map<String, Integer> users = new LinkedHashMap<String, Integer>(); SessionProvider sProvider = SessionProvider.createSystemProvider(); try { Session session = this.getSession(sProvider); QueryManager queryManager = session.getWorkspace().getQueryManager(); StringBuilder sb = new StringBuilder(); sb.append("SELECT * FROM exo:LoginHisSvc_userProfile WHERE") .append(" exo:LoginHisSvc_lastLogin >= " + Long.toString(fromTime)) .append(" AND exo:LoginHisSvc_beforeLastLogin > 0") .append(" ORDER BY exo:LoginHisSvc_lastLogin DESC"); QueryImpl query = (QueryImpl) queryManager.createQuery(sb.toString(), Query.SQL); QueryResult result = query.execute(); NodeIterator nodeIterator = result.getNodes(); while (nodeIterator.hasNext()) { Node node = nodeIterator.nextNode(); String userId = node.getProperty("exo:LoginHisSvc_userId").getString(); long numberOfLogin = node.getNode(LOGIN_HISTORY).getProperty("exo:LoginHisSvc_loginHistory_lastIndex").getLong(); users.put(userId, (int) numberOfLogin); } return users; } catch (Exception e) { LOG.debug("Error while getting login history of users " + e.getMessage(), e); } finally { sProvider.close(); } return null; } public long getBeforeLastLogin(String userId) throws Exception { SessionProvider sProvider = SessionProvider.createSystemProvider(); try { Session session = this.getSession(sProvider); Node homeNode = session.getRootNode().getNode(HOME); return !homeNode.hasNode(userId) ? 0 : homeNode.getNode(userId).getProperty("exo:LoginHisSvc_beforeLastLogin").getLong(); } catch (Exception e) { LOG.debug("Error while retrieving " + userId + "'s last login: " + e.getMessage(), e); throw e; } finally { sProvider.close(); } } }